package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"sync"
	"syscall"
	"time"
)

// 配置结构
type Config struct {
	Port          int             `json:"port"`
	LogFile       string          `json:"logFile"`
	Versions      []ConfigVersion `json:"versions"`
	AdminPassword string          `json:"adminPassword"`
}

// 版本配置
type ConfigVersion struct {
	Name        string            `json:"name"`
	Title       string            `json:"title"`
	ServerName  string            `json:"serverName"`
	ServerInfo  string            `json:"serverInfo"`
	ServerStats map[string]string `json:"serverStats"`
}

// 页面数据
type PageData struct {
	Title          string
	ServerName     string
	ServerInfo     string
	ServerStats    map[string]string
	LastUpdated    string
	Versions       []ConfigVersion
	CurrentVersion string
	StatusMessage  string
}

// 全局变量
var (
	config    Config
	logger    *log.Logger
	server    *http.Server
	templates = make(map[string]*template.Template)
	mutex     sync.Mutex
)

func main() {
	// 初始化配置
	initConfig()

	// 初始化模板
	initTemplates()

	// 注册路由
	registerRoutes()

	// 启动服务器
	startServer()

	// 处理重启信号
	handleSignals()
}

// 初始化配置
func initConfig() {
	// 确保配置文件存在
	configFile := "config.json"
	if _, err := os.Stat(configFile); os.IsNotExist(err) {
		// 如果配置文件不存在，创建默认配置
		defaultConfig := Config{
			Port:          8080,
			LogFile:       "app.log",
			AdminPassword: "admin123",
			Versions: []ConfigVersion{
				{
					Name:       "virtual",
					Title:      "虚拟机演示应用/9.0.78",
					ServerName: "虚拟机演示应用",
					ServerInfo: "欢迎使用虚拟机服务器演示",
					ServerStats: map[string]string{
						"服务器版本":    "ubuntu22",
						"服务器内置JVM": "17.0.7",
						"操作系统":     "Linux 5.15.0-78-generic",
						"JVM版本":    "17.0.7+7-LTS",
						"JVM供应商":   "Oracle Corporation",
					},
				},
				{
					Name:       "modern",
					Title:      "Web Server Dashboard",
					ServerName: "Go Web Server",
					ServerInfo: "这是一个现代化的服务器仪表盘",
					ServerStats: map[string]string{
						"服务器版本":  "Go HTTP Server/1.21",
						"运行时间":   "0h 15m 30s",
						"CPU使用率": "5.2%",
						"内存使用率":  "12.7%",
						"请求总数":   "1,254",
						"平均响应时间": "23ms",
					},
				},
			},
		}

		// 将默认配置写入文件
		configData, err := json.MarshalIndent(defaultConfig, "", "  ")
		if err != nil {
			fmt.Printf("创建默认配置文件失败: %v\n", err)
			os.Exit(1)
		}

		if err := ioutil.WriteFile(configFile, configData, 0644); err != nil {
			fmt.Printf("写入默认配置文件失败: %v\n", err)
			os.Exit(1)
		}

		fmt.Printf("已创建默认配置文件: %s\n", configFile)
	}

	// 读取配置文件
	data, err := ioutil.ReadFile(configFile)
	if err != nil {
		fmt.Printf("读取配置文件失败: %v\n", err)
		os.Exit(1)
	}

	// 解析配置文件
	if err := json.Unmarshal(data, &config); err != nil {
		fmt.Printf("解析配置文件失败: %v\n", err)
		os.Exit(1)
	}

	// 初始化日志
	initLogger()

	logger.Println("配置加载成功")
}

// 初始化日志记录器
func initLogger() {
	// 确保日志目录存在
	logDir := filepath.Dir(config.LogFile)
	if logDir != "" {
		if err := os.MkdirAll(logDir, 0755); err != nil {
			fmt.Printf("创建日志目录失败: %v\n", err)
			os.Exit(1)
		}
	}

	// 打开日志文件
	logFile, err := os.OpenFile(config.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("打开日志文件失败: %v\n", err)
		os.Exit(1)
	}

	// 创建日志记录器
	logger = log.New(logFile, "", log.LstdFlags)

	// 同时输出到控制台
	multiWriter := io.MultiWriter(os.Stdout, logFile)
	logger = log.New(multiWriter, "", log.LstdFlags)

	logger.Println("日志系统初始化成功")
}

// 初始化模板
func initTemplates() {
	tmpl, err := template.ParseFiles("templates/index.html")
	if err != nil {
		logger.Fatalf("解析模板失败: %v", err)
	}
	templates["index"] = tmpl
	logger.Println("模板加载成功")
}

// 注册路由
func registerRoutes() {
	http.HandleFunc("/", homeHandler)
	http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "favicon.ico")
	})
	http.HandleFunc("/change-version", changeVersionHandler)
	http.HandleFunc("/restart", restartHandler)
	logger.Println("路由注册成功")
}

// 启动服务器
func startServer() {
	addr := fmt.Sprintf(":%d", config.Port)
	server = &http.Server{Addr: addr}

	go func() {
		logger.Printf("服务器启动在 http://localhost%s\n", addr)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Fatalf("服务器启动失败: %v", err)
		}
	}()
}

// 处理信号
func handleSignals() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)

	for sig := range sigChan {
		switch sig {
		case syscall.SIGHUP:
			logger.Println("收到重启信号，正在重启服务器...")
			restartServer()
		case syscall.SIGINT, syscall.SIGTERM:
			logger.Println("收到停止信号，正在关闭服务器...")
			if err := server.Shutdown(nil); err != nil {
				logger.Printf("服务器关闭失败: %v", err)
			}
			logger.Println("服务器已关闭")
			os.Exit(0)
		}
	}
}

// 重启服务器
func restartServer() {
	mutex.Lock()
	defer mutex.Unlock()

	// 关闭当前服务器
	if server != nil {
		server.Shutdown(nil)
	}

	// 重新加载配置
	initConfig()

	// 重新加载模板
	initTemplates()

	// 重新注册路由
	registerRoutes()

	// 重新启动服务器
	startServer()

	logger.Println("服务器重启成功")
}

// 首页处理器
func homeHandler(w http.ResponseWriter, r *http.Request) {
	version := r.URL.Query().Get("version")
	if version == "" {
		version = config.Versions[0].Name
	}

	var selectedVersion ConfigVersion
	for _, v := range config.Versions {
		if v.Name == version {
			selectedVersion = v
			break
		}
	}

	// 准备模板数据
	data := PageData{
		Title:          selectedVersion.Title,
		ServerName:     selectedVersion.ServerName,
		ServerInfo:     selectedVersion.ServerInfo,
		ServerStats:    selectedVersion.ServerStats,
		LastUpdated:    time.Now().Format("2006-01-02 15:04:05"),
		Versions:       config.Versions,
		CurrentVersion: version,
	}

	// 执行模板
	if err := templates["index"].Execute(w, data); err != nil {
		http.Error(w, "无法渲染页面", http.StatusInternalServerError)
		logger.Printf("渲染页面失败: %v", err)
	}
}

// 更改版本处理器
func changeVersionHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Redirect(w, r, "/", http.StatusFound)
		return
	}

	version := r.FormValue("version")
	http.Redirect(w, r, "/?version="+version, http.StatusFound)
}

// 重启处理器
func restartHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Redirect(w, r, "/", http.StatusFound)
		return
	}

	password := r.FormValue("password")
	if password != config.AdminPassword {
		http.Redirect(w, r, "/?status=invalid_password", http.StatusFound)
		return
	}

	// 异步重启服务器
	go func() {
		// 等待响应发送后再重启
		time.Sleep(500 * time.Millisecond)
		restartServer()
	}()

	http.Redirect(w, r, "/?status=restarting", http.StatusFound)
}
